閉包(Closure)在MDN的解釋為: 是函式以及該函式被宣告時所在的作用域環境(lexical environment)的組合。
這樣看起來好像有聽沒有懂,比較白話文的解釋是:
假如我們想要做一個水果的計算程式,首先針對蘋果做計算:
var count = 0;
function countApples() {
count +=1;
console.log(count + ' Apples');
}
countApples(); // 1 Apples
countApples(); // 2 Apples
countApples(); // 3 Apples
接著繼續寫其他程式,寫一寫發現又需要計算橘子的數量,所以接著寫:
var count = 0;
function countApples() {
count +=1;
console.log(count + ' Apples');
}
//其他程式...
var count = 0;
function countOranges() {
count +=1;
console.log(count + ' Oranges');
}
countApples(); // 1 Apples
countApples(); // 2 Apples
countApples(); // 3 Apples
countOranges(); // 4 Orange (我們要的結果是: 1 Orange)
countOranges(); // 5 Orange (我們要的結果是: 2 Orange)
countOranges(); // 6 Orange (我們要的結果是: 3 Orange)
當我在最後執行這兩個函式後發現,它把蘋果跟橘子的數量全部都做累加了!!!
原因是在這段程式裡,我不小心把 count
變成了 全域變數
,讓程式無法辨別現在是要針對蘋果還是橘子做計算,而把它當成同一個count
全部做加總。所以,這時我們就要使用閉包來解決這個問題了!
我們將剛剛的countApples
、countOranges
分別放入各自的函式appleFunc()
、orangeFunc()
中,如此一來就可以避免count
暴露在全域環境當中,count
只有在appleFunc() 及 orangeFunc() 裡面才可以被存取,在函式外是無法存取的。
像這樣在一個fucntion內包另一個function,並在外層函式 return 內層函式供最外層使用,通常就是使用到了閉包概念。
function appleFunc(){
var count = 0;
function countApples() { //是內部函式,是一個閉包
count +=1;
console.log(count + ' Apples');
}
return countApples
}
function orangeFunc() {
var count = 0;
function countOranges() { //是內部函式,是一個閉包
count +=1;
console.log(count + ' Oranges');
}
return countOranges
}
var myAppleFunc = appleFunc();
var myOrangeFunc = orangeFunc();
myAppleFunc(); //1 Apples
myOrangeFunc(); //1 Oranges
myAppleFunc(); //2 Apples
myAppleFunc(); //3 Apples
myOrangeFunc(); //2 Oranges
myOrangeFunc(); //3 Oranges
myOrangeFunc(); //4 Oranges
這樣就成功的讓myAppleFunc()
、myOrangeFunc()
內的count
分開計算,不互相干擾了。
資料來源:
https://pjchender.blogspot.com/2017/05/javascript-closure.html
https://wcc723.github.io/javascript/2017/12/13/javascript-closure/